package com.qianfeng.netty.http;

//
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖镇楼                  BUG辟易  
//          佛曰:  
//                  写字楼里写字间，写字间里程序员；  
//                  程序人员写程序，又拿程序换酒钱。  
//                  酒醒只在网上坐，酒醉还来网下眠；  
//                  酒醉酒醒日复日，网上网下年复年。  
//                  但愿老死电脑间，不愿鞠躬老板前；  
//                  奔驰宝马贵者趣，公交自行程序员。  
//                  别人笑我忒疯癫，我笑自己命太贱；  
//  


import com.qianfeng.netty.http.anno.Controller;
import com.qianfeng.netty.http.anno.RequestMapping;
import sun.nio.cs.ext.JIS_X_0201;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * Created by Jackiechan on 2022/4/1 20:14
 * 帮我们解析并保存请求地址和方法之间的关系
 * @author Jackiechan
 * @version 1.0
 * @since 1.0
 */
public class RquestUtils {

    public static Map<String, Method> url2Method = new HashMap<>();
    public static Map<String, Object> url2Controller = new HashMap<>();

    public static void jiexi() {
        CompletableFuture.runAsync(() -> {
            //解析所有的controler
            Package package1 = RquestUtils.class.getPackage();
          //  System.err.println(package1);
            String packName = package1.getName();
            //System.err.println(package1.getName());
            String path = packName.replace(".", "\\");//因为我们要找所有的类,需要通过文件系统加载,然后才可以处理,所以先转成路径
            System.err.println(path);
        //  上面的地址是一个相对路径,需要在项目所在的位置之后拼接.所以我们必须知道当前项目的所在的位置
            URL url = RquestUtils.class.getClassLoader().getResource(".");
           // System.err.println(url);
            if (url.getProtocol().startsWith("file")) {
                //代表是一个文件路径
                String jueduilujing = url.toString().replace("file:/", "");
              //  System.err.println(jueduilujing);
                File file = new File(jueduilujing + path);//拿到了我们当前所在的位置
                try {
                    digui(file,packName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.err.println(url2Method);
                System.err.println(url2Controller);
            }






        });
    }

    public static void digui(File file,String packName) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        File[] files = file.listFiles();//找到里面所有的文件
        for (File file1 : files) {
            //获取到每一个文件
            if (file1.isDirectory()) {
               // System.err.println(file1.getName());
                digui(file1,packName+"."+file1.getName());
            }else{
                //当前是一个文件,我们就要处理这个文件,这个文件很可能就是我们要的class文件
                //获取到文件的路径,判断是不是class结尾
               // System.err.println(file1.getName());
                String fileName = file1.getName();//获取到文件名了.包含.class
                //先把filename 的后缀去掉,然后在之前的package的基础上加上这个名字就是我们的类名
                String zuizhongFileName = fileName.replace(".class", "");
                String className = packName + "." + zuizhongFileName;//拼接出当前的类名
                System.err.println("current "+className);
                Class<?> aClass = Class.forName(className);//反射加载成class文件
                //按照springmvc的流程,先看看是不是一个controller
                Controller controller = aClass.getAnnotation(Controller.class);//从类上面看看有没有这个注解
                //注意有可能这个类没有这个注解
                if (controller != null) {
                    Object instance = aClass.newInstance();//最终用于执行方法的类的对象
                    //有注解
                    System.err.println("hava anno===>"+className);//看看哪个类上面有这个注解
                    // 有注解的再获取上面的requestmapping注解,拿到值(如果有的话),这个类上面的mapping要拼接方法上面的地址才可以做成最终的的值
                    RequestMapping requestMapping = aClass.getAnnotation(RequestMapping.class);//获取类上面的地址映射的注解
                    String requesturlPre = "";//我们的请求地址的前缀,实际上要替换为类上面的注解的值,没有的话就是""
                    if (requestMapping != null) {
                        requesturlPre = requestMapping.value();//将类上面的请求地址的值设置给临时变量
                    }
                    //遍历所有的方法,找到方法上面的注解,解析注解,拿到地址,拼接上面的mapping的地址,组成一个最终的地址,这个地址和当前的方法就是一个对应的关系
                    Method[] methods = aClass.getMethods();//那到所有方法
                    for (Method method : methods) {
                     //   System.err.println(method.getName());
                        //遍历每一个方法,拿到上面的请求映射的注解,然后拿到对应的地址,这个地址和上面的地址拼接起来就是最终的地址,我们就可以和当前方法建立关系了
                        RequestMapping methodAnnotation = method.getAnnotation(RequestMapping.class);
                        if (methodAnnotation != null) {
                            String methodUrl = methodAnnotation.value();//方法上面的地址
                            String requestUrl = requesturlPre + methodUrl;//拼接出最终的访问地址
                            System.err.println(requestUrl);
                            url2Method.put(requestUrl, method);//将地址和方法建立关系
                            url2Controller.put(requestUrl, instance);//执行方法需要当前类的对象,把对象和当前的请求也建立映射关系
                        }
                    }
                }

            }
        }
    }


    public static void main(String[] args) {
        jiexi();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
